package com.snail.auth.service;

import com.snail.auth.dao.AuthAuthorityRep;
import com.snail.auth.dao.AuthMenuRep;
import com.snail.auth.dao.AuthRoleRep;
import com.snail.auth.entity.AuthAuthority;
import com.snail.auth.entity.AuthRole;
import com.snail.auth.entity.AuthUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Auther: houyanfeng 2018/12/5
 * @Description:
 */
@Service
@Transactional
public class AuthAuthorityService {
    @Autowired
    private AuthAuthorityRep authorityRep;
    @Autowired
    private AuthRoleRep roleDao;
    @Autowired
    private AuthMenuRep menuRep;
    @Autowired
    private AuthMenuService menuService;
    @Autowired
    private AuthUserService userService;

    public List<AuthAuthority> list() {
        return authorityRep.findAll();
    }

    public String getAuths(Long userId) {
        AuthUser user = userService.getByKey(userId);
        List<AuthRole> roles = user.getRoles();
        StringBuilder authStrs = new StringBuilder();
        Set<AuthAuthority> auths = new HashSet<>();
        for (AuthRole role : roles) {
            auths.addAll(role.getAuthorities());
        }
        for (AuthAuthority auth : auths) {
            authStrs.append(auth.getValue()).append(",");
        }
        return "," + authStrs.toString();
    }

    public AuthAuthority save(AuthAuthority entity) {
        return authorityRep.save(entity);
    }

    public void del(Long id) {
        authorityRep.deleteById(id);
    }

    public AuthAuthority getByKey(Long id) {
        return authorityRep.getById(id);
    }

    public List<AuthAuthority> getByMenuId(Long menuId) {
        return authorityRep.findByMenuId(menuId);
    }

    /**
     * 根据角色ID获取具有权限信息
     */
    public List<Map<String, Object>> getByRole(Long roleId) {
        String sql = "select a.* from auth_authority a, auth_role_authority ra" +
                " where a.id = ra.authority_id and ra.role_id = " + roleId;
        return authorityRep.execSql(sql);
    }

    /**
     * 赋予权限
     */
    public void addAuth(Long roleId, String idstr) throws Exception {
        AuthRole role = roleDao.getOne(roleId);
        List<AuthAuthority> auths = role.getAuthorities();
        String[] ids = idstr.split(",");
        for (int i = 0; i < ids.length; i++) {
            if (!"".equals(ids[i].trim())) {
                Long id = Long.valueOf(ids[i].substring(ids[i].indexOf("auth_") + 5).trim());
                AuthAuthority auth = authorityRep.getOne(id);
                auths.add(auth);
            }

        }
        role.setAuthorities(auths);
        roleDao.saveAndFlush(role);
    }

    /**
     * 删除指定角色的某些权限
     */
    public void deleteAuth(Long roleId, String idstr) throws Exception {
        AuthRole role = roleDao.getOne(roleId);
        List<AuthAuthority> auths = role.getAuthorities();
        for (int i = 0; i < auths.size(); i++) {
            if (idstr.contains("auth_" + auths.get(i).getId() + ",")) {
                auths.remove(i);
                i--;
            }
        }
        role.setAuthorities(auths);
        roleDao.saveAndFlush(role);
    }

    /**
     * 获取符合element使用的多级结构树
     */
    public List<Map<String, Object>> treeData() {
        List<Map<String, Object>> result = new ArrayList<>();
        List<Map<String, Object>> datas = menuRep.execSql("select id, name, parent_id as parentId from auth_menu where flag=0 order by sort");
        List<AuthAuthority> authorities = authorityRep.findAll();
        for (AuthAuthority auth : authorities) {
            Map<String, Object> authMap = new HashMap<>();
            authMap.put("id", "auth_" + auth.getId());
            authMap.put("name", auth.getName());
            authMap.put("parentId", auth.getMenuId());
            datas.add(authMap);
        }
        Map<String, List<Map<String, Object>>> midMap = new HashMap<>();
        for (Map<String, Object> data : datas) {
            if (!midMap.containsKey(data.get("parentId").toString())) {
                midMap.put(data.get("parentId").toString(), new ArrayList<>());
            }
            midMap.get(data.get("parentId").toString()).add(data);
        }
        return pushTreeData(result, midMap, "0");
    }

    private List<Map<String, Object>> pushTreeData(List<Map<String, Object>> result, Map<String, List<Map<String, Object>>> midMap, String parentId) {
        for (Map<String, Object> firMenu : midMap.get(parentId)) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", firMenu.get("id"));
            map.put("name", firMenu.get("name"));
            map.put("parentId", firMenu.get("parentId"));
            if (midMap.containsKey(firMenu.get("id").toString())) {
                List<Map<String, Object>> childs = new ArrayList<>();
                for (Map<String, Object> secondMenu : midMap.get(firMenu.get("id").toString())) {
                    Map<String, Object> child = new HashMap<>();
                    child.put("id", secondMenu.get("id"));
                    child.put("name", secondMenu.get("name"));
                    child.put("parentId", secondMenu.get("parentId"));
                    if (midMap.containsKey(secondMenu.get("id").toString())) {
                        child.put("children", pushTreeData(new ArrayList<Map<String, Object>>(), midMap, secondMenu.get("id").toString()));
                    }
                    childs.add(child);
                }
                map.put("children", childs);
            }
            result.add(map);
        }
        return result;
    }
}
